﻿// Doc-Encode UTF8-BOM, Space(4), Unix(LF)
#include "pfwncli/pfwncli.h"
#include "klbutil/klb_nvector.h"
#include "klbmem/klb_mem.h"
#include "klbnet/klb_socket.h"
#include "klbnet/klb_ncm.h"
#include <assert.h>


namespace pfw {
//////////////////////////////////////////////////////////////////////////


#define PFWNCLI_NCM_NUM         32


typedef struct pfwncli_t_
{
    klb_nvector_t*              p_multi_vec;        ///< 多路复用 数组 [](klb_multiplex_t*)

    klb_nvector_t*              p_ncm_vec;          ///< ncm 数组 [](klb_ncm_t*)
}pfwncli_t;


pfwncli_t* pfwncli_create()
{
    pfwncli_t* p_pwfncli = KLB_MALLOCZ(pfwncli_t, 1, 0);

    p_pwfncli->p_multi_vec = klb_nvector_create();
    p_pwfncli->p_ncm_vec = klb_nvector_create();

    return p_pwfncli;
}

void pfwncli_destroy(pfwncli_t* p_pwfncli)
{

    KLB_FREE_BY(p_pwfncli->p_ncm_vec, klb_nvector_destroy);
    KLB_FREE_BY(p_pwfncli->p_multi_vec, klb_nvector_destroy);
    KLB_FREE(p_pwfncli);
}

int pfwncli_push_multiplex(pfwncli_t* p_pwfncli, klb_multiplex_t* p_multi)
{
    int ret = klb_nvector_push_tail(p_pwfncli->p_multi_vec, p_multi);

    return ret;
}

static klb_multiplex_t* get_multiplex_by_chnn_pfwncli(pfwncli_t* p_pwfncli, int idx_ncm)
{
    int size = klb_nvector_size(p_pwfncli->p_multi_vec);
    if (0 < size)
    {
        int idx = idx_ncm / size;
        return (klb_multiplex_t*)klb_nvector_get(p_pwfncli->p_multi_vec, idx);
    }

    return NULL;
}

static klb_ncm_t* get_ncm_by_chnn_pfwncli(pfwncli_t* p_pwfncli, int chnn)
{
    int idx = chnn / PFWNCLI_NCM_NUM;

    while (true)
    {
        int size_ncm = klb_nvector_size(p_pwfncli->p_ncm_vec);
        if (idx < size_ncm)
        {
            break;
        }

        klb_multiplex_t* p_multi = get_multiplex_by_chnn_pfwncli(p_pwfncli, size_ncm);
        assert(NULL != p_multi);

        klb_ncm_t* p_tmp_ncm = klb_ncm_create(p_multi, KLB_PROTOCOL_LOAD_ALL);

        klb_nvector_push_tail(p_pwfncli->p_ncm_vec, p_tmp_ncm);
    }

    return (klb_ncm_t*)klb_nvector_get(p_pwfncli->p_ncm_vec, idx);
}

int pfwncli_connect(pfwncli_t* p_pwfncli, int chnn, int sidx, int protocol, const char* p_host, int port)
{
    klb_socket_fd fd = klb_socket_connect(p_host, port, 0);

    if (INVALID_SOCKET == fd)
    {
        return -1;
    }

    klb_socket_t* p_socket = klb_socket_async_create(fd);
    klb_ncm_t* p_ncm = get_ncm_by_chnn_pfwncli(p_pwfncli, chnn);

    int id = klb_ncm_push(p_ncm, protocol, p_socket, NULL, 0);
    if (id < 0)
    {
        klb_socket_destroy(p_socket);
    }

    return id;
}

//////////////////////////////////////////////////////////////////////////
} // namespace pfw

//end
